package com.bsz.patrol.Service;

import com.bsz.patrol.enums.DeviceNameEnum;
import com.bsz.patrol.enums.NursingHomeEnum;
import com.bsz.patrol.mapper.ReportMapper;
import com.bsz.patrol.pojo.*;
//import com.sun.rowset.internal.Row;
//import javafx.scene.control.Cell;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.omg.CORBA.UNKNOWN;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ReportService {

    @Autowired
    private ReportMapper reportMapper;

    private String sleepDate;
    public List<DailyReport> generateDailyReport(String date) throws Exception {
        // 检查睡眠报告是否完整
        if (!isSleepReportComplete(date)) {
            throw new IllegalStateException("睡眠报告尚未完全生成，无法生成巡查报告");
        }
        // 获取昨天的日期用于查询
        String yesterday = getYesterdayDate(date);
        // 转换日期格式用于睡眠报告查询（转换为 YYYY-M-D 格式）
//        String sleepReportDate = convertToSleepReportDateFormat(date);
//        String sleepReportDate = localDate.getYear() + "-" + localDate.getMonthValue() + "-" + localDate.getDayOfMonth();

        List<DailyReport> reports = new ArrayList<>();
        List<DeviceStats> deviceStats = reportMapper.getDeviceStats();
        List<AlarmStats> alarmStats = reportMapper.getAlarmStats(yesterday);
        List<SleepReportStats> sleepStats = reportMapper.getSleepReportStats(date);

        for (DeviceStats deviceStat : deviceStats) {
            DailyReport report = new DailyReport();
            // 使用查询日期作为报告日期
            // 替换第42行原代码：
            report.setDate(java.sql.Date.valueOf(date));
//            report.setName(deviceStat.getDeptName());
            report.setName(NursingHomeEnum.getShortNameByFullName(deviceStat.getDeptName()));
            report.setTotalInstalledDevices(deviceStat.getTotalDevices());
            report.setTotalOnlineDevices(deviceStat.getOnlineCount());
            report.setTotalOfflineDevices(deviceStat.getOfflineCount());


            // 获取离线设备详情
            List<OfflineDevice> offlineDevices = reportMapper.getOfflineDevices(deviceStat.getDeptId());
            // 按设备类型统计离线数量
            Map<String, Long> offlineCountByType = offlineDevices.stream()
                    .collect(Collectors.groupingBy(
                            OfflineDevice::getDeviceType,
                            Collectors.counting()
                    ));

            // 构建离线详情字符串
            String offlineDetails = buildOfflineDetails(offlineCountByType);
            report.setOfflineDetails(offlineDetails);

            // 设置告警信息
            AlarmStats alarmStat = alarmStats.stream()
                    .filter(a -> a.getDeptId().equals(deviceStat.getDeptId()))
                    .findFirst()
                    .orElse(null);
            if (alarmStat != null) {
                report.setTotalAlarms(alarmStat.getTotalAlarms());
                report.setYesterdayNewAlarms(alarmStat.getYesterdayAlarms());
            }

            // 新增：获取告警详情并进行分类统计
            List<AlarmDetail> alarmDetails = reportMapper.getAlarmDetails(deviceStat.getDeptId(), yesterday);

            // 分类处理告警详情
            processAlarmDetails(report, alarmDetails);


            // 设置睡眠报告信息
            SleepReportStats sleepStat = sleepStats.stream()
                    .filter(s -> s.getDeptId().equals(deviceStat.getDeptId()))
//                    .filter(s -> !s.getReportDescription().startsWith("0个"))
                    .findFirst()
                    .orElse(null);
            if (sleepStat != null) {
                report.setUsableSleepReports(sleepStat.getUsableReports());
                report.setUnusableSleepReports(sleepStat.getUnusableReports());

                // 过滤掉以"0个"开头的情况
                String filteredDescription = Arrays.stream(sleepStat.getReportDescription().split("\n"))
                        .filter(desc -> !desc.startsWith("0个"))
                        .collect(Collectors.joining("\n"));
                report.setYesterdayNoReportSituation(filteredDescription);
            }

            reports.add(report);
        }

        return reports;
    }


    // 在 ReportService 中添加私有方法
    private String buildOfflineDetails(Map<String, Long> offlineCountByType) {
        if (offlineCountByType.isEmpty()) {
            return "";  // 如果没有离线设备，返回空字符串
        }

        List<String> details = new ArrayList<>();

        // 遍历统计结果，按设备类型生成描述
        for (Map.Entry<String, Long> entry : offlineCountByType.entrySet()) {
            String deviceTypeCode = entry.getKey();
            Long count = entry.getValue();

            // 获取设备类型的中文名称
            String deviceTypeName = DeviceNameEnum.getNameByCode(deviceTypeCode);
            details.add(deviceTypeName + count + "个离线");
        }

        // 用空格连接所有描述
//        return String.join("\n", details);
        // 使用系统默认换行符
        return String.join(System.lineSeparator(), details);  //这样在Excel中显示时，不同的设备类型统计信息会分行显示，提高可读性。

    }

    // 在 ReportService 中添加告警详情处理方法
    private void processAlarmDetails(DailyReport report, List<AlarmDetail> alarmDetails) {
        if (alarmDetails == null || alarmDetails.isEmpty()) {
            return;
        }

        List<String> realAlarms = new ArrayList<>();
        List<String> falseAlarms = new ArrayList<>();

        for (AlarmDetail alarmDetail : alarmDetails) {
            String alarmGroup = alarmDetail.getAlarmGroup();
            Integer groupCount = alarmDetail.getGroupCount();


            // 获取设备类型的中文名称
//            String deviceTypeName = DeviceNameEnum.getNameByCode(alarmDetail.getDeviceType());
            String deviceTypeName = formatAlarmGroupName(alarmGroup, alarmDetail.getDeviceType());

            String alarmDescription = groupCount + "个" + deviceTypeName;


            // 根据规则分类 虚假告警：包含"红外"或"离线"文字
            if (isFalseAlarm(alarmGroup)) {
//                if (alarmDetail.getAlarmGroup().contains("离线")) {
//                    // 构建告警描述字符串
//                    alarmDescription = groupCount + "个" + deviceTypeName + "离线";
//                }
//                else if (alarmDetail.getAlarmGroup().contains("红外")) {
//                    if (alarmDetail.getAlarmGroup().contains("红外报警器电池低压"))
//                        alarmDescription = groupCount + "个" + "红外电池低压";
//                }
                falseAlarms.add(alarmDescription);
            } else {
//                if (alarmDetail.getDeviceType().contains("WATCH")) {
//                    if (alarmDetail.getAlarmGroup().contains("手表SOS告警信息")) {
//                        alarmDescription = groupCount + "个" + "手表sos";
//                    }
//                }
//                if (alarmDetail.getDeviceType().contains(DeviceNameEnum.WAVVE_SLEEP_DETECTION.getCode())) {
//                    if(alarmDetail.getAlarmGroup().contains("睡眠检测呼吸过缓")) {
//                        alarmDescription = groupCount + "个" + alarmGroup;
//                    }
//                    if (alarmDetail.getAlarmGroup().contains("睡眠检测呼吸过缓心动过速")) {
//                        alarmDescription = groupCount + "个" + alarmGroup;
//                    }
//                    if(alarmDetail.getAlarmGroup().contains("呼吸过速")) {
//                        alarmDescription = groupCount + "个" + alarmGroup;
//                    }
//                }
                realAlarms.add(alarmDescription);
            }
        }

        // 设置到对应的字段
        if (!realAlarms.isEmpty()) {
            report.setYesterdayRealAlarms(String.join(System.lineSeparator(), realAlarms));
        }
        if (!falseAlarms.isEmpty()) {
            report.setYesterdayFalseAlarms(String.join(System.lineSeparator(), falseAlarms));
        }
    }

    // 判断是否为虚假告警（包含"红外"或"离线"文字）
    private boolean isFalseAlarm(String alarmGroup) {
        if (alarmGroup == null) {
            return false;
        }
        // 如果包含"红外"，则始终视为虚假告警
        if (alarmGroup.contains("红外")) {
            return true;
        }
        // 如果是真实的报警事件，则不属于虚假告警
        // 这个判断解决了告警分组中包含"报警"文字的告警事件 比如呼叫器报警 和 呼叫器 还有  烟感设备报警 和 烟感设备
        if (alarmGroup.contains("报警")) {
            return false;
        }
        // 特殊处理：烟感设备等不包含报警都应该视为虚假告警
        if (alarmGroup.contains("烟感设备") || alarmGroup.contains("呼叫器")) {
            return true; //TODO 其他设备不知道还有哪些设备 先加上这两个
        }
        // 上面这样写 规避"红外报警"被判定为真实告警
        return  alarmGroup.contains("离线") || alarmGroup.contains("心跳");
    }

    // 格式化告警分组名称，根据您的示例进行简化
    private String formatAlarmGroupName(String alarmGroup, String deviceType) {
        if (alarmGroup == null) {
            return "";
        }
        if(deviceType.equals(DeviceNameEnum.WAVVE_SLEEP_DETECTION.getCode())) {
            return replace(alarmGroup, "检测");
        }
        if (deviceType.equals(DeviceNameEnum.INFRARED_ALARM.getCode())) {
            return replace(alarmGroup, "报警器");
        }
        if (deviceType.equals(DeviceNameEnum.FLOODING.getCode())) {
            return "水浸";
        }
        if(deviceType.equals(DeviceNameEnum.SHIT_PISS.getCode())) {
            return "尿不湿";
        }
        if (deviceType.equals(DeviceNameEnum.RADAR.getCode())) {
            return replace(replace(replace(alarmGroup, "雷达"),"检测出跌倒异常"), "检测出设备");
        }
        if (deviceType.equals(DeviceNameEnum.COMBUSTIBLE_GAS.getCode())) {
            return replace(alarmGroup, "报警器");
        }
        if (deviceType.equals(DeviceNameEnum.WATCH.getCode())) {
//            return replace(alarmGroup, "告警信息").replace("触发", "");
            return replace(replace(alarmGroup, "告警信息"), "触发");
        }
        if (deviceType.equals(DeviceNameEnum.SOS_BEEPER.getCode())) {
            // 这里会有两种情况 : 呼叫器报警 和 呼叫器   第二个属于脏数据  统一sos 了
            return "sos";
        }
        if (deviceType.equals(DeviceNameEnum.AI_SOS_BEEPER.getCode())) {
            return alarmGroup;
        }
        if (deviceType.equals(DeviceNameEnum.SLEEP_DETECTION.getCode())) {
            return "(不知道还用吗)生命体征睡眠检测仪";
        }
        if (deviceType.equals(DeviceNameEnum.CLOUD_MONITORING.getCode())) {
            return alarmGroup;
        }
        if (deviceType.equals(DeviceNameEnum.SMOKE_SENSING.getCode())) {
            return replace(replace(alarmGroup, "设备"), "报警");
        }
        if (deviceType.equals(DeviceNameEnum.DOOR_AND_WINDOW_SENSOR.getCode())) {
            return replace(alarmGroup, "传感器");
        }
        if (deviceType.equals(DeviceNameEnum.DISPOSABLE_DIAPER.getCode())) {
            return alarmGroup;
        }
        if (deviceType.equals(DeviceNameEnum.IWOWN_WATCH.getCode())) {
            return replace(alarmGroup, "告警信息");  // 已停用该类型设备
        }
        if (deviceType.equals(DeviceNameEnum.KUN_HU_WEI_SLEEP_DETECTION.getCode())) {
            return "(不知道还用吗)睡眠雷达";
        }

//        // 根据您的示例进行映射
//        if (alarmGroup.contains("睡眠检测离线")) {
//            return "睡眠离线";
//        } else if (alarmGroup.contains("红外报警器报警")) {
//            return "红外";
//        } else if (alarmGroup.contains("红外报警器离线")) {
//            return "红外离线";
//        } else if (alarmGroup.contains("手表电子围栏触发")) {
//            return "手表电子围栏";
//        } else if (alarmGroup.contains("手表SOS告警信息")) {
//            return "手表sos";
//        } else if (alarmGroup.contains("呼叫器报警")) {
//            return "sos";
//        }


        // 默认返回原名称
        return DeviceNameEnum.UNKNOWN.getName();
    }

    private String replace(String alarmGroup, String target) {
        return alarmGroup.replace(target, "");
    }


    public void exportToExcel(HttpServletResponse response, String date) throws Exception {
        List<DailyReport> reports = generateDailyReport(date);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=智慧养老项目巡查" + date + ".xlsx");

        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("日常报告");

            // 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {"日期", "名称", "设备安装总数", "设备在线总数", "设备离线总数", "设备离线详情",
                    "设备离线原因", "设备离线处理方法", "告警总数", "昨日新增告警", "昨日新增真实告警",
                    "昨日新增虚假告警", "核实告警原因", "可用睡眠报告", "不可用睡眠报告",
                    "昨日睡眠报告未生成情况", "昨日睡眠报告未生成的床位", "平板使用情况",
                    "平板使用反馈", "平板反馈处理", "现场情况", "现场情况处理",
                    "现场情况处理结果", "问题记录"};

            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }

            // 在填充数据的循环中，修改为以下代码
            int rowNum = 1;
// 创建居中对齐的单元格样式
            CellStyle centerCellStyle = workbook.createCellStyle();
            centerCellStyle.setAlignment(HorizontalAlignment.CENTER);
            centerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            for (DailyReport report : reports) {
                Row row = sheet.createRow(rowNum++);

                // 日期列 - 应用居中样式和日期格式
                Cell dateCell = row.createCell(0);
                dateCell.setCellValue(report.getDate() != null ? report.getDate() : java.sql.Date.valueOf(date));



                // 设置日期格式并居中
                CellStyle dateCellStyle = workbook.createCellStyle();
                CreationHelper createHelper = workbook.getCreationHelper();
                dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy/mm/dd"));
                dateCellStyle.setAlignment(HorizontalAlignment.CENTER);
                dateCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                dateCell.setCellStyle(dateCellStyle);

                // 其他列应用居中样式
                Cell nameCell = row.createCell(1);
                nameCell.setCellValue(report.getName() != null ? report.getName() : "");
                nameCell.setCellStyle(centerCellStyle);

                Cell totalInstalledCell = row.createCell(2);
                totalInstalledCell.setCellValue(report.getTotalInstalledDevices() != null ? report.getTotalInstalledDevices() : 0);
                totalInstalledCell.setCellStyle(centerCellStyle);

                Cell totalOnlineCell = row.createCell(3);
                totalOnlineCell.setCellValue(report.getTotalOnlineDevices() != null ? report.getTotalOnlineDevices() : 0);
                totalOnlineCell.setCellStyle(centerCellStyle);

                Cell totalOfflineCell = row.createCell(4);
                totalOfflineCell.setCellValue(report.getTotalOfflineDevices() != null ? report.getTotalOfflineDevices() : 0);
                totalOfflineCell.setCellStyle(centerCellStyle);

                Cell offlineDetailsCell = row.createCell(5);
                offlineDetailsCell.setCellValue(report.getOfflineDetails() != null ? report.getOfflineDetails() : "");
                offlineDetailsCell.setCellStyle(centerCellStyle);

                Cell offlineReasonCell = row.createCell(6);
                offlineReasonCell.setCellValue(report.getOfflineReason() != null ? report.getOfflineReason() : "");
                offlineReasonCell.setCellStyle(centerCellStyle);

                Cell offlineSolutionCell = row.createCell(7);
                offlineSolutionCell.setCellValue(report.getOfflineSolution() != null ? report.getOfflineSolution() : "");
                offlineSolutionCell.setCellStyle(centerCellStyle);

                Cell totalAlarmsCell = row.createCell(8);
                totalAlarmsCell.setCellValue(report.getTotalAlarms() != null ? report.getTotalAlarms() : 0);
                totalAlarmsCell.setCellStyle(centerCellStyle);

                Cell yesterdayNewAlarmsCell = row.createCell(9);
                yesterdayNewAlarmsCell.setCellValue(report.getYesterdayNewAlarms() != null ? report.getYesterdayNewAlarms() : 0);
                yesterdayNewAlarmsCell.setCellStyle(centerCellStyle);

                Cell yesterdayRealAlarmsCell = row.createCell(10);
                yesterdayRealAlarmsCell.setCellValue(report.getYesterdayRealAlarms() != null ? report.getYesterdayRealAlarms() : "");
                yesterdayRealAlarmsCell.setCellStyle(centerCellStyle);

                Cell yesterdayFalseAlarmsCell = row.createCell(11);
                yesterdayFalseAlarmsCell.setCellValue(report.getYesterdayFalseAlarms() != null ? report.getYesterdayFalseAlarms() : "");
                yesterdayFalseAlarmsCell.setCellStyle(centerCellStyle);

                Cell alarmVerificationReasonCell = row.createCell(12);
                alarmVerificationReasonCell.setCellValue(report.getAlarmVerificationReason() != null ? report.getAlarmVerificationReason() : "");
                alarmVerificationReasonCell.setCellStyle(centerCellStyle);

                Cell usableSleepReportsCell = row.createCell(13);
                usableSleepReportsCell.setCellValue(report.getUsableSleepReports() != null ? report.getUsableSleepReports() : 0);
                usableSleepReportsCell.setCellStyle(centerCellStyle);

                Cell unusableSleepReportsCell = row.createCell(14);
                unusableSleepReportsCell.setCellValue(report.getUnusableSleepReports() != null ? report.getUnusableSleepReports() : 0);
                unusableSleepReportsCell.setCellStyle(centerCellStyle);

                Cell yesterdayNoReportSituationCell = row.createCell(15);
                yesterdayNoReportSituationCell.setCellValue(report.getYesterdayNoReportSituation() != null ? report.getYesterdayNoReportSituation() : "");
                yesterdayNoReportSituationCell.setCellStyle(centerCellStyle);

                Cell yesterdayNoReportBedsCell = row.createCell(16);
                yesterdayNoReportBedsCell.setCellValue(report.getYesterdayNoReportBeds() != null ? report.getYesterdayNoReportBeds() : "");
                yesterdayNoReportBedsCell.setCellStyle(centerCellStyle);

                Cell tabletUsageCell = row.createCell(17);
                tabletUsageCell.setCellValue(report.getTabletUsage() != null ? report.getTabletUsage() : "");
                tabletUsageCell.setCellStyle(centerCellStyle);

                Cell tabletFeedbackCell = row.createCell(18);
                tabletFeedbackCell.setCellValue(report.getTabletFeedback() != null ? report.getTabletFeedback() : "");
                tabletFeedbackCell.setCellStyle(centerCellStyle);

                Cell tabletFeedbackProcessCell = row.createCell(19);
                tabletFeedbackProcessCell.setCellValue(report.getTabletFeedbackProcess() != null ? report.getTabletFeedbackProcess() : "");
                tabletFeedbackProcessCell.setCellStyle(centerCellStyle);

                Cell onsiteSituationCell = row.createCell(20);
                onsiteSituationCell.setCellValue(report.getOnsiteSituation() != null ? report.getOnsiteSituation() : "");
                onsiteSituationCell.setCellStyle(centerCellStyle);

                Cell onsiteProcessCell = row.createCell(21);
                onsiteProcessCell.setCellValue(report.getOnsiteProcess() != null ? report.getOnsiteProcess() : "");
                onsiteProcessCell.setCellStyle(centerCellStyle);

                Cell onsiteProcessResultCell = row.createCell(22);
                onsiteProcessResultCell.setCellValue(report.getOnsiteProcessResult() != null ? report.getOnsiteProcessResult() : "");
                onsiteProcessResultCell.setCellStyle(centerCellStyle);

                Cell issueRecordCell = row.createCell(23);
                issueRecordCell.setCellValue(report.getIssueRecord() != null ? report.getIssueRecord() : "");
                issueRecordCell.setCellStyle(centerCellStyle);
            }


            workbook.write(response.getOutputStream());
        }
    }

    private String getYesterdayDate(String date) {
        // 实现日期计算逻辑
        return LocalDate.parse(date).minusDays(1).toString();
    }


    // 在 ReportService 中添加新的方法

    /**
     * {@link ReportService#getYesterdayDate(String)}
     * @param date
     * @return
     */
    public boolean isSleepReportComplete(String date) {

        List<DeviceStats> deviceStats = reportMapper.getDeviceStats();
        // 转换日期格式用于睡眠报告查询（转换为 YYYY-M-D 格式）
        sleepDate = date;
        String sleepReportDate = convertToSleepReportDateFormat(date);
        List<SleepReportStats> sleepStats = reportMapper.getSleepReportStats(date);
        // 正常日期先查一遍睡眠报告  如果查询结果不完整 再用转换格式的日期查一遍
        // 因为 睡眠报告那边 有些日期是 2024-06-01  有的就是 2024-6-1 这种格式的 那边不规范 只能自己兼容性处理了
        if (sleepStats != null && sleepStats.size() > 0 && sleepStats.get(0).getReportCount() != sleepStats.get(0).getTotalDevices()) {
            sleepStats = reportMapper.getSleepReportStats(sleepReportDate);
            // 这里加一个sleepDate变量 是为了最上面的方法再次查询睡眠报告时使用 避免再次判断是否需要转换日期格式
            sleepDate = sleepReportDate;
        }

        // 创建映射便于查找 x
        Map<Long, SleepReportStats> sleepStatsMap = sleepStats.stream()
                .collect(Collectors.toMap(SleepReportStats::getDeptId, s -> s));

        // 检查每个部门的睡眠报告是否完整
        for (DeviceStats deviceStat : deviceStats) {
            SleepReportStats sleepStat = sleepStatsMap.get(deviceStat.getDeptId());

            // 如果某个部门没有睡眠报告数据，则不完整
//            if (sleepStat == null) {
//                return false;
//            }
            // 上面这个先注释 因为有的机构没有睡眠设备 也就没有睡眠报告  现在改成有就检查 没有就跳过
            if (sleepStat == null) {
                continue;
            }

            // 检查睡眠报告数量是否等于设备总数
            if (!sleepStat.getReportCount().equals(sleepStat.getTotalDevices())) {
                return false;
            }
//            if(sleepStat.getReportCount() != deviceStat.getTotalDevices()) {
//                return false;
//            }
        }

        return true;
    }

    // 添加日期格式转换方法
    private String convertToSleepReportDateFormat(String date) {
        try {
            LocalDate localDate = LocalDate.parse(date);
            // 转换为不补零的格式: YYYY-M-D
            return localDate.getYear() + "-" + localDate.getMonthValue() + "-" + localDate.getDayOfMonth();
        } catch (Exception e) {
            // 如果解析失败，返回原始日期
            return date;
        }
    }
}